home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
giochi
/
amigainf.lha
/
Inform
/
examples
/
balances.inf
< prev
next >
Wrap
Text File
|
1995-08-02
|
70KB
|
1,774 lines
! ----------------------------------------------------------------------------
! Balances: An exercise in parsing Release 2, 25/9/94
! updated 6/10/94
!
! This short story was written to demonstrate large-scale programming of
! the parser, and features multiple objects, complicated plurals, variable
! verbs, objects named by the player and questions. The spell-casting
! system is written in a "safe" way so that it could easily be transplanted,
! and is as "object-oriented" as seemed sensible to the author.
!
! A number of minor slips in Release 1 have been corrected, and those who
! reported them are gratefully thanked; and many suggestions have been
! added. A few others I've reluctantly declined in the interests of
! keeping the source code reasonably clean as an example program
! which compiles as a Standard as well as an Advanced game.
! Oh, and apologies to all those who think lleps of rezrov is vorzer.
!
! Needs Inform 5.4 or later to compile.
!
! This is slightly updated because the original did not properly work as
! an Advanced game (it was originally written as Standard), because it
! rather lazily got the first 2-byte word of the property list for "name"
! by the usage thing.name rather than properly looking up the 0th word
! in the array by (thing.&name)-->0 (thing.&name is the address of the
! list of data in the name property). Anyway, sorry.
! ----------------------------------------------------------------------------
Switches d;
Constant Story "BALANCES";
Constant Headline "^An Interactive Short Story^\
Copyright (c) 1994 by Graham Nelson.^";
Release 2;
Constant OBJECT_SCORE 5;
Constant MAX_SCORE 51;
! Constant DEBUG;
Include "Parser";
Include "VerbLib";
! ----------------------------------------------------------------------------
! The white featureless cubes from "Spellbreaker", which can be identified
! by being written on with the magic burin, so that their names are given
! by the player in the course of play
!
! A particularly witty thing to do is to give several of them the same name,
! or to frotz some of them to distinguish them from the others...
! And the game will have no problem with this.
! ----------------------------------------------------------------------------
Attribute is_cube;
global cube_text_buffer data 8;
global the_named_word = 0;
Fake_Action Baptise;
Class cube_class
with number 0 0 0 0,
description "A perfect white cube, four inches on a side.",
parse_name
[ i j flag;
if (parser_action==##TheSame)
{ for (i=0:i<8:i++)
if ((parser_one.&number)->i
~= (parser_two.&number)->i) return -2;
return -1;
}
for (::i++)
{ j=NextWord(); flag=0;
if (j=='cube' or 'white' ||
(j=='featureless' or 'blank' &&
((self.&number)->0) == 0)) flag=1;
if (j=='cubes')
{ flag=1; parser_action=##PluralFound; }
if (flag==0 && ((self.&number)->0) ~= 0)
{ wn--;
if (TextReader()==0) return i;
for (j=0: j<8: j++)
if ((self.&number)->j ~= cube_text_buffer->j)
return i;
flag=1;
}
if (flag==0) return i;
}
],
article "a",
short_name
[ i; if (((self.&number)->0) == 0) print "featureless white cube";
else
{ print "~";
while (((self.&number)->i) ~= 0)
print char (self.&number)->i++;
print "~ cube";
}
rtrue;
],
plural
[; RunRoutines(self, short_name); print "s";
],
before
[ i; Baptise: wn = the_named_word;
if (TextReader()==0) return i;
for (i=0: i<8: i++)
(self.&number)->i = cube_text_buffer->i;
self.article="the";
print "It is now called "; DefArt(self); ".";
],
has is_cube scored;
! Copies word "wn" from what the player most recently typed, putting it as
! plain text into cube_text_buffer, returning false if no such word is there
[ TextReader point i j len;
for (i=0:i<8:i++) cube_text_buffer->i = 0;
if (wn > parse->1) { wn++; rfalse; }
i=wn*4+1; j=parse->i; point=j+buffer; len=parse->(i-1);
for (i=0:i<len && i<7:i++) cube_text_buffer->i = point->i;
wn++; rtrue;
];
Object burin "magic burin"
with name "magic" "magical" "burin" "pen",
description
"This is a magical burin, used for inscribing objects with words \
or runes of magical import. Such a burin also gives you the \
ability to write spell scrolls.",
before
[; WriteOn:
if (second has is_cube)
{ if (second notin player)
"To write on a cube, you need to be holding it first.";
if (burin notin player)
"You would need some powerful implement for that.";
<<Baptise second>>;
}
if (second has is_spell_book)
"If a burin could write in a spell book, you wouldn't need \
the gnusto spell!";
if (second has is_scroll)
"You cannot write just anything on the magic parchment of \
a scroll: you can only ~copy~ a spell to it.";
];
[ WriteOnSub; "Graffiti is banned."; ];
[ CopyToSub;
if (burin notin player) "You need to be holding the burin to copy a spell.";
if (second has is_spell_book)
"If a burin could write in a spell book, you wouldn't need \
the gnusto spell!";
if (second hasnt is_scroll) "You can only copy spells to scrolls.";
if (child(second)~=0)
"The scroll is already full of incantation.";
"The scroll is not blank, only illegible.";
];
! ----------------------------------------------------------------------------
! Now the whole spell-casting system
! ----------------------------------------------------------------------------
Attribute is_spell;
Attribute is_scroll alias talkable; ! These are both
Attribute is_spell_book alias female; ! dodges, in case compiling in old V3
Property long magic;
[ SpellName obj; print_addr (obj.&name)-->0; ];
Class spell_class
with name "spell" "spells", article "the", number 0,
short_name
[; SpellName(self); print " spell"; rtrue;
],
before
[; Examine: SpellName(self); print " spell: ", object self; rtrue;
],
has is_spell;
Object memory "memory"
with capacity 5,
number 1,
before
[ i j k;
Examine:
objectloop (i in self) if (i.number==100) j++;
if (j>0)
{ print "The ";
objectloop (i in self)
if (i.number==100)
{ k++; SpellName(i);
if (k==j-1) print " and ";
if (k<j-1) print ", ";
}
if (j==1) print " spell is"; else print " spells are";
print " yours forever. Other than that, y";
}
else print "Y";
print "ou have ";
j=0; k=0;
objectloop (i in self) if (i.number<100) j++;
if (j>0)
{ print "the ";
objectloop (i in self)
if (i.number<100)
{ k++;
PrintShortName(i);
if (i.number==2) print " (twice)";
if (i.number==3) print " (thrice)";
if (i.number==4) print " (four times)";
if (i.number>=5) print " (many times)";
if (k==j-1) print " and ";
if (k<j-1) print ", ";
}
}
else print "no spells";
" memorised.";
Insert:
if (second.number==100) "You always know that spell.";
self.number=self.number+1;
print "Using your best study habits, you commit the ";
SpellName(second);
print " spell to memory";
if (second notin self) second.number=0;
move second to self;
second.number=second.number+1;
if (second.number==1) print ".";
if (second.number==2) print " once again.";
if (second.number==3) print " a third time.";
if (second.number>3) print " yet another time.";
if (self.number <= self.capacity) { new_line; rtrue; }
i=youngest(self); <Remove self i>;
" You have so much buzzing around in your head, though, \
that it's likely something may have been forgotten \
in the shuffle.";
Remove:
if (second notin self || second.number==100) rtrue;
if (self.number>0) self.number=self.number-1;
second.number=second.number-1;
if (second.number==0) remove second;
rtrue;
];
Object gnusto_spell "copy a scroll into your spell book" memory
class spell_class
with name "gnusto",
number 100,
magic
[ i a_book;
if (second has is_spell_book)
"Unlike scrolls, spell books are magically guarded against \
the 'theft' of their lore.";
if (second==0 || second hasnt is_scroll)
"Your spell fizzles vaguely out.";
if (second notin player)
"A gnusto spell would require close scrutiny of the scroll \
it is to copy: which you do not seem to be holding.";
objectloop (i in player)
if (i has is_spell_book) a_book=i;
if (a_book==0)
"Your spell fails, as you have no spell book.";
i=child(second);
if (i==0 || i hasnt is_spell)
{ print "Your spell fails, as "; DefArt(second);
" is illegible.";
}
<Learn a_book i>; remove second;
print "Your spell book begins to glow softly. Slowly, ornately, \
the words of "; DefArt(i); " are inscribed, \
glowing even more brightly then the book itself. \
The book's brightness fades, but the spell remains! \
However, the scroll on which it was written vanishes as \
the last word is copied.";
];
Class spell_book_class
with magic 0,
capacity 16,
before
[ p i; Open, Close:
CDefArt(self); " is always open to the right place, but it \
is also always closed. This eliminates tedious leafing and \
hunting for spells. Many lives have been saved by this \
magical innovation.";
Attack:
print "When you are done, "; DefArt(self); " remains unmarred.";
Learn:
if (self.magic==0) "(This spell book has no pages.)";
p = self.magic;
for (i=0:i<self.capacity && (p-->i)~=0:i++) ;
if (i==self.capacity) rtrue;
p-->i = second;
rtrue;
],
after
[ p i j; Examine:
if (self.magic==0) "(This spell book has no pages.)";
p = self.magic;
for (i=0:i<self.capacity && (p-->i)~=0:i++)
{ j=p-->i; <Examine j>; new_line;
}
rtrue;
],
has is_spell_book;
Class scroll_class
with parse_name
[ i j; j=-1;
if (self has general)
{ if (child(self)~=0 && child(self) has is_spell)
j=(child(self).&name)-->0; else j='illegible';
}
while (NextWord()==j or 'scroll' or (self.&name)-->0) i++;
return i;
],
before
[ i; Examine:
i=child(self);
give self general;
if (i==0 || i hasnt is_spell)
"The scroll has faded, and you cannot read it.";
print "The scroll reads ~"; <Examine i>; "~.";
],
invent
[; if (inventory_stage==2 && self has general)
{ if (child(self)==0 || child(self) hasnt is_spell)
print " (which is illegible)";
else
{ print " (of "; DefArt(child(self)); print ")"; }
}
],
has is_scroll;
[ ReadableSpell i j k;
if (scope_stage==1) return 1;
if (scope_stage==2)
{ objectloop (i in player)
if (i has is_spell_book)
{ for (k=0:k<i.capacity && (i.magic)-->k~=0:k++)
{ j=(i.magic)-->k; PlaceInScope(j);
}
}
rtrue;
}
"No such spell is in any spell book you're holding.";
];
[ SpellsSub; <Examine memory>; ];
[ LearnSub; if (location==thedark)
print "(The magic writing of the spells casts enough light \
that you can read them.)^";
<Insert memory noun>;
];
global the_spell_was = gnusto_spell;
[ CastOneSub; <Cast the_spell_was noun>; ];
Property long unmagic;
[ CastSub;
the_spell_was = noun; <Remove memory noun>;
if (noun has general)
{ give noun ~general;
if (RunRoutines(noun,unmagic)~=0) rfalse;
"Nothing happens.";
}
if (second~=0)
{ ResetVagueWords(second); ! Set "it", "him", "her"
if (RunRoutines(second,before)~=0) rfalse; ! Run before routine(s)
}
if (RunRoutines(noun,magic)~=0) rfalse;
"Nothing happens.";
];
[ InScope i;
if (verb_word=='c#cast' or 'cast')
objectloop (i in memory) PlaceInScope(i);
rfalse;
];
[ ParserError;
if (verb_word=='cast')
"You have not learned such a spell.";
rfalse;
];
[ UnknownVerb word i;
objectloop (i in memory)
if (word==(i.&name)-->0) { the_spell_was = i; return 'c#cast'; }
rfalse;
];
[ PrintVerb v;
if (v=='c#cast') { print "cast a spell at"; rtrue; }
rfalse;
];
! ----------------------------------------------------------------------------
! And now, on with the story. First, some global variables:
! ----------------------------------------------------------------------------
global prepared_flag = 0; ! Prepared for resurrection?
global hearing_good = 0; ! Sharp hearing?
global number_filled = 0; ! Sockets in the temple filled
global all_my_spells data 32; ! Array for contents of your spell book
global helistars_spells data 32; ! ...and Helistar's
! ----------------------------------------------------------------------------
! A "questions" verb. Thus,
! "who is my friend helistar"
! "what was the great change"
! and so on are recognised.
! ----------------------------------------------------------------------------
Object questions "qs";
[ QuerySub;
print_paddr noun.description; new_line;
];
[ Topic i;
if (scope_stage==1) return 0;
if (scope_stage==2)
{ objectloop (i in questions) PlaceInScope(i);
rtrue;
}
"At the moment, even the simplest questions confuse you.";
];
Object q1 "q1" questions
with name "helistar" "my" "friend" "colleague",
description
"Helistar is your colleague, an Enchanter like you who has been much \
on your mind lately. She has been investigating some very dark \
magic indeed, and seems not to be around any more. You feel rather \
vague about the details.";
Object q2 "q2" questions
with name "magical" "magic" "burin",
description "A burin is an engraving and writing tool.";
Object q3 "q3" questions
with name "change" "great",
description
"Something you had a lot to do with, but what exactly? No, it's gone.";
Object q4 "q4" questions
with name "cyclops",
description
"A one-eyed giant, usually hostile. (Don't they teach anything at \
adventurer school these days?)";
Object q5 "q5" questions
with name "grue",
description
"The grue is a sinister, lurking presence in the dark places of the \
earth. Its favorite diet is adventurers, but its insatiable appetite \
is tempered by its fear of light. No grue has ever been seen by the \
light of day, and few have survived its fearsome jaws to \
tell the tale.";
Object q6 "q6" questions
with name "grimoire",
description
"According to Chambers English Dictionary, a grimoire is ~a magician's \
book for calling up spirits~.";
! ----------------------------------------------------------------------------
! Some multiple objects, coins in fact, coded in deluxe fashion:
! ----------------------------------------------------------------------------
Attribute is_coin;
Class coin_class
with name "coin",
description "A round unstamped disc, presumably part of the local \
currency.",
parse_name
[ i j w;
if (parser_action==##TheSame)
{ if ((parser_one.&name)-->0 == (parser_two.&name)-->0) return -1;
return -2;
}
w=(self.&name)-->0;
for (::i++)
{ j=NextWord();
if (j=='coins') parser_action=##PluralFound;
else if (j~='coin' or w) return i;
}
],
has is_coin;
Class gold_coin_class
class coin_class,
with name "gold",
plural "gold coins";
Class silver_coin_class
class coin_class,
with name "silver",
plural "silver coins";
Class bronze_coin_class
class coin_class,
with name "bronze",
plural "bronze coins";
Object coin1 "silver coin"
class silver_coin_class;
[ TossCoinSub; if (noun notin player) "You need to be holding the coin first.";
move noun to parent(player);
if (location==thedark) "You throw it away into the darkness.";
if (random(20)==1) "You toss the coin, and it lands... on its edge, \
amazingly.";
"You toss the coin, and it comes up... blank, since neither side is \
marked.";
];
! ----------------------------------------------------------------------------
! The player's spell book, and three initial spells (to go with gnusto):
! ----------------------------------------------------------------------------
Object spell_book "spell book"
class spell_book_class,
with name "spell" "book" "my" "spellbook",
description "My Spell Book^";
Object frotz_spell "cause an object to give off light"
class spell_class,
with name "frotz",
magic
[; if (second==0) "There is a brief, blinding flash of light.";
if (second has animate)
"The spell, not designed for living creatures, goes sour.";
if (parent(second)==compass)
"The spell dissipates vaguely.";
give second light;
print "There is an almost blinding flash of light as "; DefArt(second);
print " begins to glow! It slowly fades to a less painful level, but ";
DefArt(second); " is now quite usable as a light source.";
],
unmagic
[; if (second==0) "There is a brief moment of deep darkness.";
if (second has animate)
"The spell, not designed for living creatures, goes sour.";
if (parent(second)==compass)
"The spell dissipates vaguely.";
if (second hasnt light)
{ CDefArt(second); " isn't producing light as it is."; }
give second ~light;
print "A pool of darkness coagulates around "; DefArt(second);
print " but slowly fades back to normality. Still, ";
DefArt(second); " is no longer any kind of light source.";
];
Object rezrov_spell "open even locked or enchanted objects"
class spell_class,
with name "rezrov",
magic
[; if (second==0) "The world is open already.";
if (second has animate)
"It might be a boon to surgeons if it worked, but it doesn't.";
if (second has open || second hasnt openable)
"It doesn't need opening.";
if (second hasnt locked)
{ give second open; CDefArt(second); " opens obediently. \
Like swatting a fly with a sledge hammer, if you ask me.";
}
give second open ~locked;
print "Silently, "; DefArt(second); " swings open.";
],
unmagic
[; if (second==0) "The world is closed already.";
if (second has animate)
"Happily, that is unnecessary.";
if (second has locked || second hasnt lockable)
"It doesn't need locking.";
give second ~open locked;
print "Silently, "; DefArt(second); " swings shut and locks.";
];
Object yomin_spell "mind probe"
class spell_class,
with name "yomin",
magic
[; if (second==0 || second hasnt animate)
"That must be either vegetable or mineral.";
if (second==player) "You give yourself a mild headache.";
print "You look into the rather ordinary thoughts of ";
DefArt(second); ".";
],
unmagic
[; if (second==0 || second hasnt animate)
"That must be either vegetable or mineral.";
if (second==player) "You give yourself a mild headache.";
CDefArt(second); " is rather shocked, for some reason.";
];
! ----------------------------------------------------------------------------
! The first scene: the Hut and its (rather easy) secret
! ----------------------------------------------------------------------------
Object Hut "Ramshackle Hut"
with description
"Until quite recently, someone lived here, you feel sure. \
Now the furniture is matchwood and \
the windows are glassless. Outside, it is a warm, sunny day, \
and grasslands extend to the low hills on the horizon.",
out_to Grasslands,
cant_go "There's only the one room: better go ~out~.",
name "windows" "grasslands" "grass" "hills",
has light;
Nearby furniture "wooden furniture"
with name "furniture" "broken" "wood" "wooden",
before
[; Examine, Search, LookUnder:
self.before=0; score=score+5;
move h_box to player;
"Searching through the furniture, which is good for nothing \
but firewood now, you come across an old cedarwood box.";
],
has scenery;
Object h_box "cedarwood box"
with name "cedar" "cedarwood" "wooden" "box",
description "The box bears the calligraphed initial H."
has container openable lockable locked;
Nearby helistars_book "Helistar's grimoire"
class spell_book_class,
with name "grimoire" "helistar" "helistars",
description "This must be the grimoire of dangerous spells kept by \
your irresponsible friend Helistar. Many pages are \
missing, but a few spells remain:^",
has proper;
! ----------------------------------------------------------------------------
! Grasslands and the valley
! ----------------------------------------------------------------------------
Object Grasslands "Grasslands, near Hut"
with name "grasslands" "grass" "hut" "path",
description
"The grasslands sway over low hills in all directions: it is a \
peaceful wilderness, broken only by this hut and a faint path \
to the north.",
in_to Hut,
n_to Valley,
cant_go "You wander around for a while but end up back at the hut."
has light;
Object Valley "Pocket Valley"
with name "valley" "trail",
description
"A pleasant pocket valley in the grassy hills, through which a \
trail runs north-to-south.",
n_to "The trail runs out to nothing, and you retreat for fear of \
getting so lost you couldn't find the hut again by nightfall.",
cant_go "You wander around the pleasant valley, but are afraid to \
lose sight of the trail.",
s_to Grasslands
has light;
[ RideSub; print "You can hardly ride "; IndefArt(noun); "."; ];
Nearby horse "horse"
with short_name
[; if (self has general) print "winged horse";
else print "chestnut horse";
rtrue;
],
parse_name
[ i j; if (self has general) j='winged'; else j=-1;
while (NextWord()==j or 'horse' or 'chestnut') i++;
return i;
],
describe
[; print "There is "; InDefArt(self);
" here, munching on a pile of oats.";
],
before
[; Cast: if (the_spell_was == bozbar_spell)
{ give self general;
"A pair of handsome brown wings suddenly appears on \
the horse's powerful shoulders. The horse turns in a \
complete circle, a look of puzzlement on his face.";
}
if (the_spell_was == yomin_spell)
"He is mainly thinking about oats. Partly who you are \
and what you're up to, but mainly oats.";
Enter: <<Ride self>>;
Ride: if (horse hasnt general)
"You ride around for a while, exercising the horse, but \
soon enough he tires of this and pointedly brings you \
back to the oats. Obligingly you dismount and he \
begins grazing again.";
print "You begin to ride north. Then, slowly at first but with \
increasing sureness, the horse begins beating its powerful \
wings. You rise majestically through the air, sailing \
gracefully across a chasm where the hills fall away. \
The horse lands gently on the far side and deposits you, \
taking to the skies again.^";
PlayerTo(Edge); rtrue;
],
has animate;
Nearby oats "pile of oats"
with name "oats" "pile" "of",
before
[; Examine, Search, LookUnder:
self.before=0;
move shiny_scroll to player; score=score+5;
"Sifting through the oats, you find a shiny scroll! Lucky \
you got to it before the horse did.";
Take: "What would you want with all those oats?";
],
has scenery;
Object shiny_scroll "shiny scroll"
class scroll_class,
with name "shiny";
Object bozbar_spell "cause an animal to sprout wings" shiny_scroll
class spell_class,
with name "bozbar",
magic
[; if (second==0 || second hasnt animate)
"The spell dies away in vain.";
if (second==player)
"Your elbows twitch, but there is no other effect.";
print "For a moment, "; DefArt(second);
" looks highly discomforted, but the moment passes.";
],
unmagic
[; if (second==0 || second hasnt animate)
"The spell dies away in vain.";
if (second==player) "What wings?";
if (second==horse && horse has general)
{ give horse ~general;
"The Enchanter giveth, and the Enchanter taketh away. \
The horse looks disconsolate but returns to the oats.";
}
CDefArt(second); " has no wings to lose.";
];
! ----------------------------------------------------------------------------
! The Chasm and the snake
! ----------------------------------------------------------------------------
Object Edge "Edge of Chasm"
with name "wide" "chasm" "road" "daffodils",
description
"The road ends suddenly at a wide chasm. The road leads upward \
to the north, and you can see it continuing on the southern side \
of the chasm.",
u_to Up_Road, n_to Up_Road,
cant_go "The chasm is too perilous to approach. The only safe way is \
up and to the north.",
before
[; Jump: deadflag=1; "You jump bravely into the chasm, and plunge... \
gracefully through the air. (It gets a bit less noble and \
airy after that.)";
],
has light;
Nearby snake "hissing snake"
with name "hissing" "snake",
initial
"Lying in a tight coil at the edge of the chasm is a hissing snake.",
life
[; "The snake hisses angrily!"; ],
before
[; Cast: if (the_spell_was == urbzig_spell)
{ remove self;
snakes_cube.initial =
"Beside a clump of daffodils is a featureless white cube.";
"The snake is replaced by a clump of daffodils.";
}
if (the_spell_was == bozbar_spell)
{ deadflag=1; remove self;
snakes_cube.initial =
"A featureless cube rests where the snake took off from.";
"The snake is transformed into a huge, winged serpent, \
a dragon which bellows and leaps out into the chasm, \
backwinging furiously... and knocking you over the \
edge quite by accident.";
}
if (the_spell_was == yomin_spell)
"Horrid reptilian thoughts insinuate their way into you.";
],
has animate;
Nearby snakes_cube "cube"
class cube_class,
with initial
"The snake appears to be curled around a featureless white cube.",
before
[; if (snake notin nothing) "The snake won't let you near that cube!";
];
! ----------------------------------------------------------------------------
! The crest of the hill; Icarus the tortoise; the chewed scroll
! ----------------------------------------------------------------------------
Object Up_Road "Crest of Hill"
with description
"The road crosses the top of a ridge here, sloping downwards to \
the south and the northwest. A track diverges to east.",
nw_to Cave_Mouth, s_to Edge, d_to Edge, e_to Track,
has light;
Nearby tortoise "tortoise"
with name "tortoise" "turtle",
initial "A tortoise ambles along the road, extremely slowly.",
life
[; "The tortoise (slowly) turns its neck to look at you (stupidly).";
],
before
[; Cast: if (the_spell_was == urbzig_spell)
"Just how safe do you want your surroundings to be?";
if (the_spell_was == bozbar_spell)
{ move chewed_scroll to parent(self); remove self;
StartDaemon(self); score=score+5;
"The tortoise seems to be incapable of expressing \
surprise, but is now soaring away high in the sky. \
Something rather grubby is left behind.";
}
if (the_spell_was == yomin_spell)
"For a moment you think there is nothing there, as you \
chew absentmindedly on a leaf. But somewhere inside \
the tortoise is a sense of wonder at the amazing blue \
canopy of the sky.";
],
daemon
[ i; if (location ~= Up_Road or Track || random(6)~=1) rfalse;
if (random(4)==1 && self hasnt general)
{ move feather to location; give self general;
"^A tortoise-feather flutters to the ground before you!";
}
i=random(3);
if (i==1) print "^High in the sky,";
if (i==2) print "^Far above you,";
if (i==3) print "^Tiny in the blue sky,";
" a tortoise flaps across the sun.";
],
has animate;
Object torn_scroll "torn scroll"
class scroll_class,
with name "torn";
Nearby lobal_spell "sharpen hearing"
class spell_class,
with magic
[; if (second==0 || second hasnt animate)
"There is a loud bang in your ear, but no other effect.";
if (second==player)
{ if (hearing_good==1) "There is no further effect.";
hearing_good=1; StartTimer(self, 5);
"Nothing happens, possibly because those butterflies on the \
other side of the hill keep distracting you.";
}
CDefArt(second);
" is no doubt grateful for the gift of sharper hearing.";
],
unmagic
[; if (second==0 || second hasnt animate)
"There is a brief silence, but no other effect.";
if (second==player) { StopTimer(self); hearing_good=0; "Pardon?"; }
CDefArt(second);
" is no doubt grateful not to have to listen to you.";
],
time_left 0,
time_out
[; if (hearing_good==0) rfalse;
hearing_good=0;
"^Those wretched butterflies finally shut up.";
],
name "lobal";
Object chewed_scroll "chewed scroll"
class scroll_class,
with initial "It looks as if the tortoise was chewing something - once \
it might have been a scroll, but now it's chewed up like \
a lettuce leaf.",
before
[; Cast: if (the_spell_was == caskly_spell)
{ move torn_scroll to parent(self);
remove self; score=score+5;
"Before your eyes, the scroll begins to repair itself, \
failing only at the very last tear. Not quite perfect \
perhaps, but certainly a readable, if torn scroll.";
}
],
with name "chewed";
Object feather "tortoise feather"
with name "tortoise" "feather",
description
"Possibly your rarest, and also least valuable, possession.";
! ----------------------------------------------------------------------------
! The cave mouth and the perfect sapphire
! ----------------------------------------------------------------------------
Object Cave_Mouth "Cave Mouth"
with name "gorse" "footpath" "cave" "mouth",
description
"This is a cave mouth, at one end of a road which winds southeast \
over rising ground. The entrance west to the caves is dark. \
Only a footpath runs further north, into gorse.",
u_to Up_Road, se_to Up_Road, in_to Iron_Door, w_to Iron_Door,
n_to Footpath
has light;
Nearby Iron_Door "iron door"
with name "iron" "door" "heavy",
description "It just looks like an ordinary heavy iron door.",
door_dir
[; if (location==Cave_Mouth) return w_to; return e_to;
],
door_to
[; if (location==Cave_Mouth) return In_Cave;
return Cave_Mouth;
],
describe
[; if (self has open) "^The iron door stands open.";
if (self hasnt locked) "^The iron door is unlocked but shut.";
"A heavy iron door bars the cave mouth.";
],
found_in In_Cave Cave_Mouth
has static door openable locked lockable;
! Cf. T. S. Eliot, "Burnt Norton" II:
Nearby sapphire "perfect sapphire"
with name "perfect" "sapphire" "gemstone" "gem",
initial "Clotted in the mud beside the door is a perfect sapphire.",
before
[; Examine: remove self; move caskly_spell to memory;
<Learn spell_book caskly_spell>;
caskly_spell.number=100;
"As you gaze into the perfect blue of the sapphire, \
you feel your mind begin to reel. Unable to bear \
the naked sight of perfection, you look away, ashamed. \
As you do so, the sapphire cracks and wastes away to \
thin hot dust. But something remains, something in your \
mind...";
];
Object caskly_spell "cause perfection"
class spell_class,
with name "caskly",
magic
[; if (second==0) "Trying to make everything perfect was a little \
too ambitious.";
if (second==player) "Oh, don't be too hard on yourself.";
if (second==helistars_book)
"Your spell is not powerful enough to restore the lost pages.";
CDefArt(second); " looks pretty perfect as is.";
];
! ----------------------------------------------------------------------------
! Inside the Cave, the powerful urbzig spell and its consequences
! ----------------------------------------------------------------------------
Object In_Cave "Inside Cave"
with description
"A wide but shallow cave not far inside the hill. There is no \
obvious exit, except for the way you came in.",
out_to
[; if (CoinsIn(left_pan)+CoinsIn(right_pan) < 6)
"Something bars your way, and you hear \
the scales jangling militantly. You were trying to \
steal its coins!";
if (scales.number~=0) "Something bars your way, and you hear \
the scales jangle slightly with energy.";
return Iron_Door;
],
cant_go "The only way is back ~out~ through the iron door.",
after
[; Take: if (parent(noun)==left_pan or right_pan)
{ print "Taken from "; DefArt(parent(noun)); "."; }
];
Nearby cave_cube "cube"
class cube_class,
with initial "Balanced on a rock formation is a featureless white cube.";
Nearby scales "pair of scales"
with name "pair" "of" "scales" "pans", number 0,
describe
[; print "^A fair-sized pair of scales hangs from a bracket in the \
cave wall. ";
if (self.number==0) "The scales are balanced.";
if (self.number==1) "The left-hand side is higher.";
"The right-hand side is higher.";
],
before
[; "There are left and right hand pans, which you should refer to \
individually.";
],
has static supporter;
Class pan_class
with name "pan" "side" "tray",
before
[; Receive: if (noun has is_scroll || noun has is_coin) rfalse;
if (noun==feather) rfalse;
"The pans gleam with what almost seems greed, and somehow they \
contrive to nudge your hand past them with your worthless and \
boring item.";
],
after
[ i j d w1 w2; Receive, LetGo: i=scales.number;
objectloop (j in left_pan) w1=w1 + WeightOf(j);
objectloop (j in right_pan) w2=w2 + WeightOf(j);
if (w1==w2) scales.number=0;
if (w1 > w2) scales.number=-1;
if (w1 < w2) scales.number=1;
j=scales.number; d=(w2-w1)*(scales.number);
if (j==i) rfalse;
if (j==0) "The scales come into balance.";
if (j==1) print "The left pan "; else print "The right pan ";
if (d==1) "very slowly rises up.";
"rises up.";
],
has supporter scenery;
[ WeightOf obj;
if (obj==bronze_coin) return 2;
if (obj has is_scroll || obj==feather) return 1;
return 3;
];
[ CoinsIn obj i c;
objectloop (i in obj) if (i has is_coin) c++;
return c;
];
Nearby left_pan "left pan"
class pan_class,
with name "left";
Nearby right_pan "right pan"
class pan_class,
with name "right";
Object bronze_coin "bronze coin" left_pan
class bronze_coin_class;
Object coin3 "gold coin" left_pan
class gold_coin_class;
Object coin4 "gold coin" left_pan
class gold_coin_class;
Object coin5 "gold coin" right_pan
class gold_coin_class;
Object coin6 "silver coin" right_pan
class silver_coin_class;
Object coin7 "silver coin" right_pan
class silver_coin_class;
Object crumpled_scroll "crumpled scroll" left_pan
class scroll_class,
with name "crumpled";
Object urbzig_spell "turn a dangerous object into a harmless one"
crumpled_scroll
class spell_class,
with name "urbzig",
magic
[; if (second==0) "The spell fizzles away.";
if (second==player) "It's a matter of opinion, isn't it?";
if (second==helistars_book or mace || second has is_cube)
{ CDefArt(second); remove second;
if (second==mace && cyclops in location)
{ remove cyclops; move eye_cube to location;
" turns into a featureless white cube just as the cyclops \
was about to hit you with it. Mightily embarrassed \
by this, he drops the cube and runs off!";
}
print " turns into a moth and flutters away.^";
rtrue;
}
print "Nothing obvious happens. Perhaps "; DefArt(second);
" isn't so very dangerous after all.";
],
unmagic
[; if (second==0) "The spell fizzles away.";
if (second==player) "It's a matter of opinion, isn't it?";
if (second has static || second has scenery)
{ print "Your spell is too weak for something quite as \
monumentally harmless as "; DefArt(second); ".";
}
if (second==helistars_book or snake || second has is_cube
|| second==cyclops or mace)
"Nothing obvious happens.";
if (second in player)
{ remove second; deadflag=1;
"Suddenly, a tarantula races up your arm to your throat! \
Perhaps it was unwise to gizbru something you were \
actually holding.";
}
if (cyclops has general)
"Nothing happens. Perhaps that's just as well, \
after the last time.";
move cyclops to location;
remove second; give cyclops general; StartTimer(cyclops, 5);
CDefArt(second); " is replaced by a buck-toothed cyclops \
wielding a mace!";
];
Object cyclops "buck-toothed cyclops"
with name "buck" "toothed" "buck-toothed" "cyclops",
initial "A huge buck-toothed cyclops menaces you, armed with a \
heavy mace!",
before
[; Cast: if (the_spell_was == bozbar_spell)
"Does the term ~death wish~ mean anything to you?";
if (the_spell_was == urbzig_spell)
"The cyclops bellows with glee as your spell has \
no effect. (After all, he wouldn't be ~dangerous~ if \
an urbzig spell worked on him, would he?)";
],
life [; "He roars incoherently, swinging the mace!"; ],
time_left 0,
time_out
[; if (self notin location)
{ remove self; rtrue;
}
deadflag=1; remove mace; remove cyclops;
"Feeling that he's given you quite long enough to explain why \
you made such a mess of his life, he swings the great mace \
maniacally down on you!";
],
each_turn
[ i; i=random(4); if (i==1) "^The cyclops leaps and bellows!";
if (i==2)
"^Whirling the mace, the cyclops jabbers at you incoherently.";
if (i==3)
"^The cyclops is losing patience (the appropriate cyclops \
word is untranslatable into English, but approximately means \
~forbearance in not smashing all nearby skulls~).";
"^The cyclops jabs you with the mace, almost breaking your rib.";
],
has animate transparent;
Nearby mace "mace"
with name "heavy" "mace" "axe",
description "It looks much too heavy for you to even lift.";
Nearby eye_cube "cube"
class cube_class,
with initial
"A featureless white cube lies where the cyclops dropped it.";
! ----------------------------------------------------------------------------
! The Footpath and the carpet
! ----------------------------------------------------------------------------
Object Footpath "Gorse Bushes"
with description
"The footpath from the cave mouth runs into dense, impenetrable \
gorse bushes. Perhaps it wasn't so much a footpath as a rill \
in the earth where roots wouldn't take; anyway, there's no way \
but back south.",
s_to Cave_Mouth
has light;
Nearby carpet "beautiful red carpet"
with name "beautiful" "magic" "red" "carpet",
initial
"Slung over one of the gorse bushes is a beautiful red carpet.",
description
"This is a carpet of unusual design. It is red, beautifully woven \
and bears a pattern of cubes.",
before
[ i; Receive:
if (self notin location || self hasnt moved)
"Not until the carpet's on the ground, you can't.";
Ride: <<Enter self>>;
Enter:
if (self notin location || self hasnt moved)
"Not until the carpet's on the ground, you can't.";
if (location==Temple)
"Mysteriously, the carpet rucks and pulls until you're \
thrown off. It settles back on the white floor with a \
contented sigh.";
if (location==In_Cave)
"The carpet rises suddenly, crashing into the roof of \
cave and throwing you back off again. Painfully.";
if (location==Bazaar) i=Up_Road; else i=Bazaar;
print "The carpet rises suddenly into the fluffy white \
clouds, and after a headlong journey deposits you...^";
move self to i;
PlayerTo(i,1); move player to self; <<Look>>;
Take: if (player in self) "Not while you're on it!";
for (i=child(self):i~=0:i=child(self))
{ move i to location;
print "(Dislodging "; DefArt(i); print ")^";
}
],
has supporter enterable;
! ----------------------------------------------------------------------------
! A Bazaar Lottery
! ----------------------------------------------------------------------------
Object Bazaar "Crowded Bazaar"
with description
"This is a crowded, noisy bazaar. Directly in front of you is \
a lottery! But the contemptuous-looking barker is doing a \
very poor trade: hardly anyone wants his first prize, the \
big cuddly toy elephant, or even his nineteenth prize, a \
featureless white cube.",
each_turn
[ i; i=random(4);
if (i==1)
"^~Roll up! Roll up! One silver piece for three goes!~";
if (i==2)
"^~Come on, then! Just a silver coin gets you three!~";
if (i==3)
"^~Think what you could win, all for one silver coin!~";
"^~This could be your lucky day!~";
],
before
[; Learn:
"~None of that!~ snaps the barker angrily, putting you off \
your study habits. He mutters about ~Enchanter cheats~, \
but under the circumstances you decide to let the insult \
pass.";
],
cant_go "Everywhere, the crowds of jabbering natives block your way \
to all the good stalls. In fact, the only one you can get at is \
this dismal lottery.",
has light;
global last_called = 1;
Nearby board "lottery board"
with number 0,
name "board" "lottery" "holes",
description
"There are a hundred holes each way, making, um, let's see, yes, \
ten thousand tickets in all. Still, there are nineteen prizes, \
so your odds must be, oh, well, not too awful anyway.",
before
[ i; if (action==##LetGo)
{ if (self.number==0) "The barker stabs you in the chest with \
his finger. ~That's a silver coin to you, bub!~";
for (i=taken_t1: i<=taken_t6: i++)
if (last_called == i.number)
"That ticket's already taken.";
self.number=self.number - 1;
for (i=taken_t1: i<=taken_t6: i++)
if (parent(i)==0)
{ i.number = last_called; itobj = i;
move i to player; give i moved proper;
print "You take "; DefArt(i); " out of the board.";
}
}
if (action~=##Examine) "The barker is burly, and won't let you \
tamper with the board.";
],
initial
"Behind the barker is a huge drilled board, and inside each little \
numbered hole is a rolled-up lottery ticket."
has static container open;
Class ticket_class
with number -1, name "ticket",
description
[; if (self.number==2306) "It is labelled ~First Prize~!";
if (self.number==5802) "It is labelled ~Nineteenth Prize~.";
"~You lose,~ says the ticket, with a smily face. ~Try again!~";
],
short_name
[; if (self.number==-1) rfalse;
print "lottery ticket ", self.number; rtrue;
],
parse_name
[ i j w;
if (NextWord()~='lottery' or 'ticket') return 0;
i=1;
if (NextWord()=='lottery' or 'ticket') { i++; wn++; }
w=TryNumber(wn-1);
if (w==-1000) return i;
if (w==0) return 0;
if (self.number==-1)
{ for (j=taken_t1: j<=taken_t6: j++)
if (w == j.number) rfalse;
}
else
{ if (self.number~=w) return 0;
}
i++; last_called = w; return i;
],
before
[; Examine:
if (self in board) "That would be cheating!";
Cast: "~Get outta here, bub!~, the barker says, disgusted.";
];
Object ticket_in_board "rolled-up ticket" board
class ticket_class;
Object taken_t1 "t1" class ticket_class;
Object taken_t2 "t2" class ticket_class;
Object taken_t3 "t3" class ticket_class;
Object taken_t4 "t4" class ticket_class;
Object taken_t5 "t5" class ticket_class;
Object taken_t6 "t6" class ticket_class;
Object barker "barker" Bazaar
with name "barker" "burly" "man",
number 0,
description
"A boxer gone to seed who failed as a magician all down the \
coast, that'd be your guess.",
life
[; Attack, Kiss: "No way. He must weigh twice what you do.";
Ask: if (second=='prize' or 'prizes')
"~Just one silver coin and a prize could be yours!~";
if (second=='white' or 'featureless' or 'cube')
"He blows the dust off it. ~Genuine antique, that.~";
if (second=='elephant' or 'toy' or 'cuddly')
"~Good quality merchandise,~ he says, in a way that \
suggests he can only spell one of those three words.";
if (second=='ticket' or 'tickets' or 'lottery')
"~Three tickets for one silver coin!~";
"~Just play the game, bub.~";
Order, Answer: "The barker glowers at you.";
Give: if ((noun.&name)-->0 == 'ticket')
{ remove noun;
if (noun.number==2306)
{ move elephant to player; give elephant moved;
Bazaar.description =
"This is a crowded, noisy bazaar. Directly in front of you is \
the lottery!";
"With very bad grace, the barker shoves the \
cuddly toy elephant into your arms.";
}
if (noun.number==5802)
{ move barker_cube to player; give barker_cube moved;
Bazaar.description =
"This is a crowded, noisy bazaar. Directly in front of you is \
the lottery!";
score=score+5;
"With concealed relief, the barker shoves the \
featureless white cube into your hands.";
}
"~Bad luck! You lose!~";
}
if (self.number==2) "~You've had enough goes already!~ he \
growls. No wonder trade is bad.";
if (noun hasnt is_coin) "~What do you call that? One silver \
coin to play!~";
if ((noun.&name)-->0 == 'bronze')
"~Bronze! Not a chance, sunshine.~";
remove noun;
board.number = board.number + 3; self.number=self.number+1;
if ((noun.&name)-->0 == 'gold')
"Gleefully the barker snatches the gold coin. ~Sorry \
bub, no change. Business is slack today!~";
"Grudgingly the barker takes the silver coin and stands \
back to let you at the board, arms folded.";
],
before
[; Cast: if (the_spell_was == bozbar_spell)
"He's not that much of an animal.";
if (the_spell_was == lobal_spell)
"His problem is listening, not hearing.";
if (the_spell_was == caskly_spell)
"For a moment his hair seems to comb itself. Irritated, \
he ruffles it again, and the spell dies an ignominious \
death.";
if (the_spell_was == yomin_spell)
{ if (elephant has moved || barker_cube has moved)
"The barker's mind is a heap of grumbles about lost \
prizes and scrawny Enchanters.";
if (self hasnt general)
{ give self general;
"~Hope that scrawny Enchanter doesn't pick 2306!~ \
thinks the barker (slowly).";
}
"~If that mark does win, hope it's only worthless \
old 5802,~ ponders the barker.";
}
],
has animate scenery;
Object prizes "prizes" Bazaar
with name "prize" "prizes",
before [; "~Hands off those prizes!~"; ],
has scenery;
Object elephant "cuddly toy elephant"
with name "cuddly" "toy" "elephant",
description "Pink, cuddly, toy, elephant. Says it all, really.",
before
[; Cast: if (the_spell_was == bozbar_spell)
"Let me get this straight. You, the enchanter who \
defeated Krill, the head of the Borphee Guild \
himself... are attempting to grow wings on a pink \
cuddly elephant?";
];
Object barker_cube "cube"
class cube_class;
! ----------------------------------------------------------------------------
! The spells in Helistar's grimoire
! ----------------------------------------------------------------------------
Object lleps_spell "reverse effect of memorised spell"
class spell_class,
with name "lleps",
magic
[; if (second==0 || parent(second)~=memory)
"The spell backfires, painfully.";
if (second.number==100)
"You know that spell too well for your mind to be able \
to accept the change.";
if (second has general) give second ~general;
else give second general;
print "Your mind wrenches as "; DefArt(second);
" reverses itself.";
],
unmagic
[; RunRoutines(self,magic); rtrue;
];
Object mortin_spell "cause immediate death of caster"
class spell_class,
with name "mortin",
magic
[; deadflag=1;
"You really can't fault Helistar on this one. Death is \
absolutely immediate, like a sudden blackout curtain...";
],
unmagic
[; prepared_flag=1;
"Nothing quite happens... and yet you feel enormously more \
confident as you go about this dangerous world.";
];
! ----------------------------------------------------------------------------
! Death and the Boneyard
! ----------------------------------------------------------------------------
[ AfterLife i;
if (prepared_flag==0) rfalse;
if (parent(player)==Balance_Room)
"^^Your foresight in preparing a resurrection was wasted. The \
tangled magic of the Balance Room coiled around your puny \
enchantment like a constricting serpent.";
prepared_flag=0; deadflag=0; hearing_good=0;
i=memory.capacity; if (i>1) memory.capacity = i-1;
i=parent(player);
while (child(player)~=0) move child(player) to i;
move spell_book to player;
print "^^With great foresight you prepared yourself for resurrection... \
Your mind feels a little weaker, but at least you're alive.^";
PlayerTo(Boneyard);
];
Object Boneyard "Boneyard"
with name "bones" "blades" "shoulder" "skulls",
description
"This is a room of bones. Shoulder blades make up the floor, \
skulls the walls and leg-bones the door frames. The west exit \
leads into darkness, but the doorway to the north opens onto a \
seemingly normal grassy scene.",
n_to Grasslands,
w_to "Some magical force blocks your way.",
before
[; Examine, Search:
if (noun==w_obj) "You can make out nothing to the west.";
],
has light;
Nearby worthless_scroll "worthless scroll"
class scroll_class,
with initial "You are almost treading on a worthless scroll.",
name "worthless";
Object filfre_spell "produce gratuitous fireworks" worthless_scroll
class spell_class,
with name "filfre",
magic
[; if (self hasnt scored) { score++; give self scored; }
"A brief shower of gratuitous fireworks spells out:^^\
The masterly Enchanter trilogy was written by Marc Blank, \
David Lebling and Steve Meretzky.";
],
unmagic
[; "A lengthy shower of artistically justified fireworks spells out:^^\
The masterly Enchanter trilogy was written by Jane Austen, \
Emily Bronte and Edgar Allen Poe.";
];
! ----------------------------------------------------------------------------
! The Cubical Temple
! ----------------------------------------------------------------------------
Object Track "Track, outside Temple"
with description
"This is the end of a long track winding through desolate hills, \
which runs back west up to the ridge.",
before
[; Listen:
if (hearing_good==0) "The chanting is too quiet to make out.";
"The endlessly repeating threnody of the monks tells of \
the legend of one who will some day enlighten their order, \
and so be taken up to a higher plane. He (or she, \
presumably) is known as The Four-Cubed One.";
],
w_to Up_Road, u_to Up_Road
has light;
Nearby Temple "cubical Temple"
with name "temple" "cubical" "cube" "enormous",
before
[ i j;
Enter: "The Temple is featureless and unbroken. Perhaps the top \
is open, because the sound must come from somewhere... \
but you wouldn't bet on it.";
Cast: if (the_spell_was == rezrov_spell)
"The huge temple remains impassive at your relatively \
puny enchantment.";
if (the_spell_was == frotz_spell)
{ objectloop (i in player) if (i has is_cube) j++;
if (j==0) "The temple shakes, but then is still again.";
if (j<4) "The temple shakes! White light plays \
over your hands and possessions, but then all is \
still again.";
print "The temple shakes and white light bathes you. \
Smoothly it unfolds itself in a four-dimensional \
way your senses can barely comprehend. All you \
know is that when it is over, \
you find yourself in...^";
hearing_good=0; score=score+5;
PlayerTo(Balance_Room); rtrue;
}
],
describe
[; print "^You stand outside an enormous temple in the shape of a \
perfect, featureless white cube, four hundred feet on a \
side. From somewhere within you hear the ";
if (hearing_good==1) print "bellowing noise";
else print "tiny sound";
" of the monks chanting.";
],
description
"It's much like every other gigantic temple in the shape of a \
featureless white cube you've ever seen. No obvious way in.",
has static;
! ----------------------------------------------------------------------------
! Inside the Temple
! ----------------------------------------------------------------------------
Object Balance_Room "Balance Room"
with description
"This seems to be the inside of a featureless white cube, forty \
feet on a side. The air is stale and there is no exit.",
has light;
Nearby balance_meter "image of the scales"
with name "image" "scales" "of" "pair", article "the",
initial "The image of a pair of scales hangs high in the air. One \
pan is much lower than the other.",
before [; "It's only an image."; ],
has static;
Nearby dusty_podium "dusty podium"
with name "podium" "dusty" "cobwebs" "cobwebbed",
initial "Far below the scales, in the centre of the ~floor~, is a \
predictably-shaped podium, but it is so dusty and \
cobwebbed that you can't see what it once was.",
before
[; Cast: if (the_spell_was == caskly_spell)
"Nice try, but it is protected from enchantment.";
"However dusty it is, the podium is still protected from \
casual enchantment.";
Rub: remove self; move balance_key to Balance_Room;
itobj = balance_key;
"No substitute for old-fashioned hard work, sometimes, \
and after much patient (sneezy) scrubbing, the podium \
appears in its true white glory. Set into it are four \
sockets, arranged in a two by two square.";
],
has static;
Object balance_key "podium"
with name "podium" "pedestal" "platform" "cubical",
initial "Far below the scales, in the centre of the ~floor~, is a \
predictably-shaped podium. Set into it are four sockets, \
arranged in a two by two square.",
has static supporter;
Nearby sockets "two by two square"
with name "square" "two" "by" "two",
before
[ i; if (action~=##Examine || number_filled==0)
"You'll have to say which socket you mean. \
(Let's call them ~top left~, ~bottom right~ and so on.)";
objectloop (i in self)
{ CDefArt(i);
if (child(i)==0) print " is empty.^";
else { print " contains "; IndefArt(child(i)); print ".^"; }
}
rtrue;
],
has static;
Class socket_class
with name "socket", article "the",
before
[; Cast: "The sockets are proof against magic.";
Examine: CDefArt(self); print ", cubical and slightly more \
than four inches on a side, is decorated with ";
print_paddr self.description;
if (child(self)==0) ".";
print ", and contains "; IndefArt(child(self)); ".";
Receive: if (noun hasnt is_cube) "The socket rejects that.";
if (child(self)~=0)
"There is already a cube in that socket.";
],
after
[; LetGo: number_filled--;
"With much struggle, you manage to pull the cube away.";
Receive: number_filled++;
if (number_filled==4)
{ if (snakes_cube in bl_socket
&& barker_cube in ul_socket
&& cave_cube in br_socket
&& eye_cube in ur_socket)
{ deadflag=2; score=score+5;
"As you place the final cube into the sockets, you feel \
imbued with celestial wisdom (more so than usually). \
You find yourself growing to the height of the cube, so \
that you pull the balances back level by hand, and then \
you grow still further, out of the temple until it is but \
a cube in your hand, and you are a giant towering over \
the land.^^\
Then, of course, you wake up, glumly realising it's time \
to go to your job at the new Borphee Laboratories and \
all those Wheatstone bridge experiments. But at least \
you can dream about the old days.";
}
"The sockets are all full now, but that doesn't mean \
anything's happened.";
}
"The cube is a predictably perfect fit in the socket.";
],
has static container open;
Nearby bl_socket "bottom left socket"
class socket_class
with name "bottom" "left" "serpent",
description "a serpent";
Nearby ul_socket "top left socket"
class socket_class
with name "top" "left" "bazaar",
description "a scene in a bazaar";
Nearby br_socket "bottom right socket"
class socket_class
with name "bottom" "right" "cave",
description "an engraving of a rocky cave";
Nearby ur_socket "top right socket"
class socket_class
with name "top" "right" "eye",
description "an eye";
! ----------------------------------------------------------------------------
! That's all of the object definitions: just a little code and grammar left
! ----------------------------------------------------------------------------
[ Initialise;
location = Hut;
move burin to player; move coin1 to player; move spell_book to player;
thedark.description =
"It is pitch black. You are likely to be eaten by a grue.";
! (In fact you are stone-cold certain not to be, but never mind.)
spell_book.magic = all_my_spells;
<Learn spell_book gnusto_spell>;
<Learn spell_book frotz_spell>;
<Learn spell_book yomin_spell>;
<Learn spell_book rezrov_spell>;
helistars_book.magic = helistars_spells;
<Learn helistars_book frotz_spell>;
<Learn helistars_book lleps_spell>;
<Learn helistars_book mortin_spell>;
print "^^^^^This transcript is not from the Enchanter trilogy, but it \
does show most of the usual things you can do in those stories...^^";
print "You feel a little confused as to how you got here. Something \
to do with Helistar! That's right, and how the world is so far \
off balance nowadays, after the Great Change.^^";
];
[ PrintRank;
print ", earning you the rank of ";
if (score >= 50) "Scientist.";
if (score >= 40) "Spellbreaker.";
if (score >= 30) "Sorcerer.";
if (score >= 20) "Enchanter.";
if (score >= 10) "novice Enchanter.";
"lost dreamer.";
];
[ DiagnoseSub i;
i=memory.capacity;
if (i==5) "You feel fine, and your memory is unimpaired.";
if (i==4) "You feel shaky after your brush with death, but your mental \
faculties seem sound.";
if (i==3) "For someone who has died twice, you're in reasonable shape.";
"How many times have you died now? Your memory isn't what it was.";
];
! ----------------------------------------------------------------------------
! Grammar extensions needed by the spell-casting and cube-writing rules:
! ----------------------------------------------------------------------------
Include "Grammar";
[ AnyWord; the_named_word=wn++; return burin; ];
Verb "write" "scribe"
* AnyWord "on" noun -> WriteOn;
Verb "copy" * scope=ReadableSpell "to" noun -> CopyTo;
Verb "who" "what"
* "is" scope=Topic -> Query
* "was" scope=Topic -> Query;
Verb "spells" "memory"
* -> Spells;
Verb "learn" "memorise" "memorize"
* scope=ReadableSpell -> Learn;
Extend "examine" first
* scope=ReadableSpell -> Examine;
Verb "c#cast"
* -> CastOne
* noun -> CastOne;
Verb "cast"
* is_spell -> Cast
* is_spell "at" noun -> Cast
* is_spell "on" noun -> Cast;
Verb "diagnose" "health"
* -> Diagnose;
! ----------------------------------------------------------------------------
! And one for the game itself.
! ----------------------------------------------------------------------------
Verb "ride" "mount" "straddle"
* creature -> Ride
* noun -> Enter;
Verb "flip" "toss" * is_coin -> TossCoin;
end;